package com.xueyi.workflow.service.impl;

import com.xueyi.workflow.domain.dto.StartProcessDto;
import com.xueyi.workflow.domain.dto.CompleteTaskDto;
import com.xueyi.workflow.domain.vo.TaskVo;
import com.xueyi.workflow.service.ProcessService;
import com.xueyi.common.core.web.result.AjaxResult;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.HistoryService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 流程服务实现类
 *
 * @author xueyi
 * @date 2024-07-03
 */
@Service
public class ProcessServiceImpl implements ProcessService {

    @Autowired
    private RepositoryService repositoryService;
    
    @Autowired
    private RuntimeService runtimeService;
    
    @Autowired
    private TaskService taskService;
    
    @Autowired
    private HistoryService historyService;

    /**
     * 部署流程
     */
    @Override
    public AjaxResult deployProcess(MultipartFile file) {
        try (InputStream is = file.getInputStream()) {
            Deployment deployment = repositoryService.createDeployment()
                    .addInputStream(file.getOriginalFilename(), is)
                    .name(file.getOriginalFilename())
                    .deploy();
            return AjaxResult.success(deployment.getId(), "流程部署成功");
        } catch (IOException e) {
            return AjaxResult.error("流程部署失败: " + e.getMessage());
        }
    }

    /**
     * 启动流程
     */
    @Override
    public AjaxResult startProcess(StartProcessDto dto) {
        try {
            ProcessInstance instance = runtimeService.startProcessInstanceByKey(
                    dto.getProcessDefinitionKey(),
                    dto.getBusinessKey(),
                    dto.getVariables()
            );
            return AjaxResult.success(instance.getId(), "流程启动成功");
        } catch (Exception e) {
            return AjaxResult.error("流程启动失败: " + e.getMessage());
        }
    }

    /**
     * 获取任务列表
     */
    @Override
    public AjaxResult getTasks(String assignee) {
        try {
            List<Task> tasks = taskService.createTaskQuery().taskAssignee(assignee).list();
            List<TaskVo> voList = tasks.stream().map(this::convertToTaskVo).collect(Collectors.toList());
            return AjaxResult.success(voList);
        } catch (Exception e) {
            return AjaxResult.error("获取任务列表失败: " + e.getMessage());
        }
    }

    /**
     * 完成任务
     */
    @Override
    public AjaxResult completeTask(CompleteTaskDto dto) {
        try {
            taskService.complete(dto.getTaskId(), dto.getVariables());
            return AjaxResult.success("任务完成成功");
        } catch (Exception e) {
            return AjaxResult.error("任务完成失败: " + e.getMessage());
        }
    }

    /**
     * 获取流程历史
     */
    @Override
    public AjaxResult getProcessHistory(String processInstanceId) {
        try {
            List<HistoricActivityInstance> historyList = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .orderByHistoricActivityInstanceStartTime().asc()
                    .list();
            return AjaxResult.success(historyList);
        } catch (Exception e) {
            return AjaxResult.error("查询流程历史失败: " + e.getMessage());
        }
    }

    /**
     * 将Flowable Task转换为TaskVo
     */
    private TaskVo convertToTaskVo(Task task) {
        TaskVo vo = new TaskVo();
        vo.setId(task.getId());
        vo.setName(task.getName());
        vo.setDescription(task.getDescription());
        vo.setAssignee(task.getAssignee());
        vo.setProcessInstanceId(task.getProcessInstanceId());
        vo.setProcessDefinitionId(task.getProcessDefinitionId());
        vo.setPriority(task.getPriority());
        vo.setCategory(task.getCategory());
        vo.setFormKey(task.getFormKey());
        
        // 转换时间
        if (task.getCreateTime() != null) {
            vo.setCreateTime(LocalDateTime.ofInstant(task.getCreateTime().toInstant(), ZoneId.systemDefault()));
        }
        if (task.getDueDate() != null) {
            vo.setDueDate(LocalDateTime.ofInstant(task.getDueDate().toInstant(), ZoneId.systemDefault()));
        }
        
        return vo;
    }
}
